<?php
/**
 * Eka Framework 0.3.0
 *
 * @copyright Copyright (c) 2008 Alexey Yu. Chuprina <656b61@gmail.com> (http://php-eka.googlecode.com)
 * @license http://www.opensource.org/licenses/mit-license.php MIT License
 *
 * @version $Id$
 */

require_once 'Eka/Db/Table/Abstract.php';

/**
 * Eka_Db_Table_Model
 *
 * @package Db
 * @subpackage Table
 */
class Eka_Db_Table_Model extends Eka_Db_Table_Abstract
{
	/**
	 * Classname for row
	 *
	 * @var string
	 */
	protected $rowClass;
	
	/**
	 * @var array
	 */
	protected $cache = array();
	
	/**
	 * @var bool
	 */
	protected $userCache;
	
	/**
	 * @var string
	 */
	protected $cacheKeySeparator = '.';
	
	protected $cacheKeyComposite;
	
	protected $cacheKeyColumn;
	
	public function __construct(Eka_Db_Adapter_Abstract $adapter, $tableName, $tableSchema, $rowClass, $columns, $primary)
	{
		parent::__construct($adapter, $tableName, $tableSchema);
		
		$this->rowClass = $rowClass;
		$this->columns = $columns;
		$this->primary = $primary;
		$this->columnNames = array_keys($this->columns);
		
		$this->userCache = !!$this->primary;
		$this->cacheKeyComposite = count($this->primary) > 1;
		$this->cacheKeyColumn = $this->cacheKeyComposite ? null : $this->primary[0];
	}
	
	/**
	 * @param Eka_Db_Table_Row_Model $row
	 * @return Eka_Db_Table_Row_Model
	 */
	public function addToCache(Eka_Db_Table_Row_Model $row)
	{
		if ($this->userCache) {
			$data = $row->toArray();
			if ($this->cacheKeyComposite) {
				$key = array();
				foreach ($this->primary as $column) {
					if (!isset($data[$column])) {
						return $row;
					}
					$key[] = $data[$column];
				}
				$key = join($this->cacheKeySeparator, $key);
			} else {
				if (!isset($data[$this->cacheKeyColumn])) {
					return $row;
				}
				$key = $data[$this->cacheKeyColumn];
			}
			if (!isset($this->cache[$key])) {
				$this->cache[$key] = $row;
			}
			return $this->cache[$key];
		}
		return $row;
	}
	
	/**
	 * @param array $data
	 * @return Eka_Db_Table_Row_Model
	 */
	public function cache(array $data)
	{
		return $this->addToCache(new $this->rowClass($data, false));
	}
	
	/**
	 * @param array $data
	 * @param bool $new
	 * @return Eka_Db_Table_Row_Model
	 */
	protected function getRow(array $data = null, $new = false)
	{
		while ($this->userCache) {
			if ($this->cacheKeyComposite) {
				$key = array();
				foreach ($this->primary as $column) {
					if (!isset($data[$column])) {
						break;
					}
					$key[] = $data[$column];
				}
				$key = join($this->cacheKeySeparator, $key);
			} else {
				if (!isset($data[$this->cacheKeyColumn])) {
					break;
				}
				$key = $data[$this->cacheKeyColumn];
			}
			if (!isset($this->cache[$key])) {
				$this->cache[$key] = new $this->rowClass($data, $new);
			}
			return $this->cache[$key];
		}
		return new $this->rowClass($data, $new);
	}
	
	/**
	 * @param mixed $value
	 * @return Eka_Db_Table_Row_Model
	 */
	public function getOne($value)
	{
		if ($this->userCache) {
			if ($this->cacheKeyComposite) {
				$key = join($this->cacheKeySeparator, $value);
			} else {
				$key = $value;
			}
			if (!isset($this->cache[$key])) {
				$this->cache[$key] = parent::getOne($value);
			}
			return $this->cache[$key];
		}
		return parent::getOne($value);
	}
}